use sqlite_wasm_rs::sqlite3_stmt;
use crate::db::dao::base_dao::Adder;
use crate::db::db::{Db, DbParamType};
use crate::db::pojo::pojo::{ImSensitiveWord};
use crate::db::util::{db_get_enum, db_get_int64, db_get_string, db_get_time};

const SELECT_COLUMNS: &'static str = "id, word, status statusValue, createTime, updateTime";

pub fn sensitive_word_inserts(db: Db, sensitive_words: &mut Vec<&mut ImSensitiveWord>) {
    if sensitive_words.is_empty() {
        return;
    }

    let sql = c"insert into im_sensitive_word(word, status, createTime, updateTime) values(?, ?, ?, ?)";

    let mut params = vec![];
    for sensitive_word in sensitive_words.iter() {
        let mut param = vec![];
        param.push(DbParamType::Str(&*sensitive_word.word));
        param.push(DbParamType::Byte(sensitive_word.status.clone() as i8));
        param.push(DbParamType::DateTime2(&sensitive_word.create_time));
        param.push(DbParamType::DateTime2(&sensitive_word.update_time));
        params.push(param);
    }

    log::info!("db sensitive word params {:?}", params);
    let ids = db.inserts("sensitive inserts", sql, params);
    assert_eq!(ids.len(), sensitive_words.len());
    for (idx, id) in ids.into_iter().enumerate() {
        let sensitive_word = sensitive_words.get_mut(idx).unwrap();
        sensitive_word.id = Some(id);
    }
}

pub fn sensitive_word_updates(db: Db, sensitive_words: &mut Vec<&mut ImSensitiveWord>) {
    if sensitive_words.is_empty() {
        return;
    }
    let sql = "update im_sensitive_word set status = ?, updateTime = ? where word = ?";
    let mut params = vec![];
    for feedback in sensitive_words.iter() {
        let mut param = vec![];
        param.push(DbParamType::Byte(feedback.status.clone() as i8));
        param.push(DbParamType::DateTime2(&feedback.update_time));
        param.push(DbParamType::Str(&*feedback.word));
        params.push(param);
    }
    log::info!("db sensitive word update params: {:?}", params);
    db.batch_exec("sensitive updates", sql.to_string(), params);
}

pub fn query_sensitive_word_by_word(db: Db, word: &str) -> Option<ImSensitiveWord> {
    let sql = format!("select {} from im_sensitive_word where word = ?", SELECT_COLUMNS);
    let mut params = vec![];
    params.push(DbParamType::Str(word));
    db.query_one("sensitive query", sql, params, Box::new(sensitive_word_wrap))
}

pub fn query_sensitive_words(db: Db, _user_id: &str, page_size: usize) -> Option<ImSensitiveWord> {
    let sql = format!("select {} from im_sensitive_word order by updateTime desc limit 0, {}", SELECT_COLUMNS, page_size);
    let params = vec![];
    db.query_one("sensitive query2", sql.to_string(), params, Box::new(sensitive_word_wrap))
}

pub fn sensitive_word_total(db: Db)-> usize {
    let size = unsafe {
        db.count("sensitive total", c"select count(*) from im_sensitive_word", Vec::new())
    };
    log::info!("db sensitive word count: {}", size);
    size
}



fn sensitive_word_wrap(stmt: *mut sqlite3_stmt) -> ImSensitiveWord {
    unsafe {
        let mut adder = Adder::new();
        let id = db_get_int64(stmt, adder.add());
        let word = db_get_string(stmt, adder.add()).unwrap();
        let status = db_get_enum(stmt, adder.add());
        let create_time = db_get_time(stmt, adder.add());
        let update_time = db_get_time(stmt, adder.add());

        ImSensitiveWord {
            id: Some(id),
            word,
            status,
            create_time,
            update_time,
        }
    }
}